#!/usr/bin/env python3
"""
过滤器代码自动生成器
基于配置自动生成前端、后端、测试代码
"""

import sys
import os
from pathlib import Path

# 添加项目根目录到路径
project_root = Path(__file__).parent.parent
sys.path.insert(0, str(project_root))

from config.filter_config import FILTER_CONFIGS, FilterType, get_multi_select_filters

class FilterCodeGenerator:
    """过滤器代码生成器"""
    
    def __init__(self):
        self.project_root = project_root
    
    def generate_frontend_html(self) -> str:
        """生成前端HTML过滤器部分"""
        html_parts = []
        
        for config in FILTER_CONFIGS:
            if config.filter_type == FilterType.MULTI_SELECT:
                html_parts.append(f'''
                <!-- {config.description} -->
                <div class="filter-group">
                    <label for="{config.key}">{config.label}:</label>
                    <select id="{config.key}" multiple>
                        {''.join(f'<option value="{option}">{option}</option>' for option in config.options)}
                    </select>
                </div>''')
                
            elif config.filter_type == FilterType.SINGLE_SELECT:
                html_parts.append(f'''
                <!-- {config.description} -->
                <div class="filter-group">
                    <label for="{config.key}">{config.label}:</label>
                    <select id="{config.key}">
                        <option value="">全部</option>
                        {''.join(f'<option value="{option}">{option}</option>' for option in config.options)}
                    </select>
                </div>''')
                
            elif config.filter_type == FilterType.RANGE:
                min_attr = f'min="{config.min_value}"' if config.min_value is not None else ''
                max_attr = f'max="{config.max_value}"' if config.max_value is not None else ''
                step_attr = f'step="{config.step}"'
                html_parts.append(f'''
                <!-- {config.description} -->
                <div class="filter-group range-filter">
                    <label>{config.label}:</label>
                    <div class="range-inputs">
                        <input type="number" id="{config.key}_min" placeholder="最小值" {min_attr} {step_attr}>
                        <span>-</span>
                        <input type="number" id="{config.key}_max" placeholder="最大值" {max_attr} {step_attr}>
                    </div>
                </div>''')
                
            elif config.filter_type == FilterType.NUMBER:
                min_attr = f'min="{config.min_value}"' if config.min_value is not None else ''
                max_attr = f'max="{config.max_value}"' if config.max_value is not None else ''
                step_attr = f'step="{config.step}"'
                placeholder = config.placeholder or f"输入{config.label}"
                html_parts.append(f'''
                <!-- {config.description} -->
                <div class="filter-group">
                    <label for="{config.key}">{config.label}:</label>
                    <input type="number" id="{config.key}" placeholder="{placeholder}" {min_attr} {max_attr} {step_attr}>
                </div>''')
                
            elif config.filter_type == FilterType.TEXT:
                placeholder = config.placeholder or f"输入{config.label}"
                html_parts.append(f'''
                <!-- {config.description} -->
                <div class="filter-group">
                    <label for="{config.key}">{config.label}:</label>
                    <input type="text" id="{config.key}" placeholder="{placeholder}">
                </div>''')
                
            elif config.filter_type == FilterType.BOOLEAN:
                html_parts.append(f'''
                <!-- {config.description} -->
                <div class="filter-group">
                    <label for="{config.key}">{config.label}:</label>
                    <select id="{config.key}">
                        <option value="">全部</option>
                        <option value="true">{config.options[0] if len(config.options) > 0 else '是'}</option>
                        <option value="false">{config.options[1] if len(config.options) > 1 else '否'}</option>
                    </select>
                </div>''')
        
        return '\n'.join(html_parts)
    
    def generate_frontend_js(self) -> str:
        """生成前端JavaScript过滤器逻辑"""
        
        # 生成applyFilters函数中的数据收集部分
        collect_code = []
        clear_code = []
        details_code = []
        
        for config in FILTER_CONFIGS:
            if config.filter_type == FilterType.MULTI_SELECT:
                collect_code.append(f"        {config.key}: Array.from(document.getElementById('{config.key}').selectedOptions).map(option => option.value),")
                clear_code.append(f"    document.getElementById('{config.key}').selectedIndex = -1;")
                details_code.append(f'''
    if (filters.{config.key} && filters.{config.key}.length > 0) {{
        details.push(`{config.label}: ${{filters.{config.key}.join(', ')}}`);
    }}''')
                
            elif config.filter_type == FilterType.SINGLE_SELECT:
                collect_code.append(f"        {config.key}: document.getElementById('{config.key}').value,")
                clear_code.append(f"    document.getElementById('{config.key}').value = '';")
                details_code.append(f'''
    if (filters.{config.key}) {{
        details.push(`{config.label}: ${{filters.{config.key}}}`);
    }}''')
                
            elif config.filter_type == FilterType.RANGE:
                collect_code.append(f"        {config.key}_min: document.getElementById('{config.key}_min').value,")
                collect_code.append(f"        {config.key}_max: document.getElementById('{config.key}_max').value,")
                clear_code.append(f"    document.getElementById('{config.key}_min').value = '';")
                clear_code.append(f"    document.getElementById('{config.key}_max').value = '';")
                details_code.append(f'''
    if (filters.{config.key}_min || filters.{config.key}_max) {{
        const rangeText = `${{filters.{config.key}_min || '∞'}} - ${{filters.{config.key}_max || '∞'}}`;
        details.push(`{config.label}: ${{rangeText}}`);
    }}''')
                
            elif config.filter_type == FilterType.NUMBER:
                collect_code.append(f"        {config.key}: document.getElementById('{config.key}').value,")
                clear_code.append(f"    document.getElementById('{config.key}').value = '';")
                details_code.append(f'''
    if (filters.{config.key}) {{
        details.push(`{config.label}: ${{filters.{config.key}}}`);
    }}''')
                
            elif config.filter_type == FilterType.TEXT:
                collect_code.append(f"        {config.key}: document.getElementById('{config.key}').value.trim(),")
                clear_code.append(f"    document.getElementById('{config.key}').value = '';")
                details_code.append(f'''
    if (filters.{config.key}) {{
        details.push(`{config.label}: ${{filters.{config.key}}}`);
    }}''')
                
            elif config.filter_type == FilterType.BOOLEAN:
                collect_code.append(f"        {config.key}: document.getElementById('{config.key}').value,")
                clear_code.append(f"    document.getElementById('{config.key}').value = '';")
                details_code.append(f'''
    if (filters.{config.key}) {{
        const boolText = filters.{config.key} === 'true' ? '{config.options[0] if len(config.options) > 0 else '是'}' : '{config.options[1] if len(config.options) > 1 else '否'}';
        details.push(`{config.label}: ${{boolText}}`);
    }}''')
        
        return f'''
// 自动生成的过滤器JavaScript代码

// 在applyFilters函数中使用：
const filterData = {{
{chr(10).join(collect_code)}
}};

// 在clearFilters函数中使用：
function clearAllFilters() {{
{chr(10).join(clear_code)}
}}

// 在showFilterDetails函数中使用：
function generateFilterDetails(filters) {{
    const details = [];
{chr(10).join(details_code)}
    return details;
}}'''
    
    def generate_backend_filter_logic(self) -> str:
        """生成后端过滤逻辑"""
        
        # 生成参数提取代码
        extract_code = []
        filter_code = []
        param_dict_items = []
        
        for config in FILTER_CONFIGS:
            if config.filter_type == FilterType.MULTI_SELECT:
                extract_code.append(f"    {config.key} = request.args.getlist('{config.key}')")
                param_dict_items.append(f'"{config.key}": {config.key}')
                
                if config.key == "profit_status":
                    # 特殊处理盈亏状态
                    filter_code.append(f'''
    # {config.description}
    if {config.key}:
        profit_conditions = []
        if "profitable" in {config.key}:
            profit_conditions.append(Trade.net_profit > 0)
        if "losing" in {config.key}:
            profit_conditions.append(Trade.net_profit <= 0)
        if profit_conditions:
            query = query.filter(or_(*profit_conditions))''')
                else:
                    # 标准字段过滤
                    filter_code.append(f'''
    # {config.description}
    if {config.key}:
        if {str(config.case_sensitive).lower()}:
            query = query.filter(Trade.{config.db_field}.in_({config.key}))
        else:
            conditions = [func.lower(Trade.{config.db_field}) == func.lower(value) for value in {config.key}]
            query = query.filter(or_(*conditions))''')
            
            elif config.filter_type == FilterType.SINGLE_SELECT:
                extract_code.append(f"    {config.key} = request.args.get('{config.key}')")
                param_dict_items.append(f'"{config.key}": {config.key}')
                filter_code.append(f'''
    # {config.description}
    if {config.key}:
        if {str(config.case_sensitive).lower()}:
            query = query.filter(Trade.{config.db_field} == {config.key})
        else:
            query = query.filter(func.lower(Trade.{config.db_field}) == func.lower({config.key}))''')
            
            elif config.filter_type == FilterType.RANGE:
                extract_code.append(f"    {config.key}_min = request.args.get('{config.key}_min')")
                extract_code.append(f"    {config.key}_max = request.args.get('{config.key}_max')")
                param_dict_items.append(f'"{config.key}_min": {config.key}_min')
                param_dict_items.append(f'"{config.key}_max": {config.key}_max')
                filter_code.append(f'''
    # {config.description}
    if {config.key}_min:
        try:
            min_val = float({config.key}_min)
            query = query.filter(Trade.{config.db_field} >= min_val)
        except ValueError:
            pass
    if {config.key}_max:
        try:
            max_val = float({config.key}_max)
            query = query.filter(Trade.{config.db_field} <= max_val)
        except ValueError:
            pass''')
            
            elif config.filter_type == FilterType.NUMBER:
                extract_code.append(f"    {config.key} = request.args.get('{config.key}')")
                param_dict_items.append(f'"{config.key}": {config.key}')
                filter_code.append(f'''
    # {config.description}
    if {config.key}:
        try:
            val = float({config.key})
            query = query.filter(Trade.{config.db_field} == val)
        except ValueError:
            pass''')
            
            elif config.filter_type == FilterType.TEXT:
                extract_code.append(f"    {config.key} = request.args.get('{config.key}')")
                param_dict_items.append(f'"{config.key}": {config.key}')
                if config.case_sensitive:
                    filter_code.append(f'''
    # {config.description}
    if {config.key}:
        query = query.filter(Trade.{config.db_field}.contains({config.key}))''')
                else:
                    filter_code.append(f'''
    # {config.description}
    if {config.key}:
        query = query.filter(func.lower(Trade.{config.db_field}).contains(func.lower({config.key})))''')
            
            elif config.filter_type == FilterType.BOOLEAN:
                extract_code.append(f"    {config.key} = request.args.get('{config.key}')")
                param_dict_items.append(f'"{config.key}": {config.key}')
                filter_code.append(f'''
    # {config.description}
    if {config.key}:
        if {config.key} == 'true':
            query = query.filter(Trade.{config.db_field} == True)
        elif {config.key} == 'false':
            query = query.filter(Trade.{config.db_field} == False)''')
        
        return f'''
# 自动生成的后端过滤逻辑

def extract_filter_parameters():
    """提取所有过滤器参数"""
{chr(10).join(extract_code)}
    return {{{', '.join(param_dict_items)}}}

def apply_all_filters(query, filters):
    """应用所有过滤器"""
    from sqlalchemy import or_, func
{chr(10).join(filter_code)}
    return query'''
    
    def generate_mock_test_config(self) -> str:
        """生成Mock测试配置"""
        
        test_cases = []
        
        # 为每个过滤器生成基本测试用例
        for config in get_multi_select_filters():
            if config.options:
                for option in config.options[:2]:  # 只取前两个选项作为示例
                    test_name = f"{config.key}_{option.lower().replace(' ', '_')}"
                    test_cases.append(f'''
    "{test_name}": {{
        "filters": {{"{config.key}": ["{option}"]}},
        "expected_count": 0,  # 需要根据实际数据更新
        "description": "测试{config.description} - {option}"
    }},''')
        
        return f'''
# 自动生成的Mock测试配置

GENERATED_TEST_CASES = {{
{chr(10).join(test_cases)}
}}'''
    
    def generate_all_code(self):
        """生成所有代码并保存到文件"""
        
        print("🚀 开始生成过滤器代码...")
        
        # 创建输出目录
        output_dir = self.project_root / "generated"
        output_dir.mkdir(exist_ok=True)
        
        # 生成前端HTML
        html_code = self.generate_frontend_html()
        with open(output_dir / "filter_html.html", "w", encoding="utf-8") as f:
            f.write(html_code)
        print("✅ 生成前端HTML代码")
        
        # 生成前端JavaScript
        js_code = self.generate_frontend_js()
        with open(output_dir / "filter_js.js", "w", encoding="utf-8") as f:
            f.write(js_code)
        print("✅ 生成前端JavaScript代码")
        
        # 生成后端过滤逻辑
        backend_code = self.generate_backend_filter_logic()
        with open(output_dir / "filter_backend.py", "w", encoding="utf-8") as f:
            f.write(backend_code)
        print("✅ 生成后端过滤逻辑")
        
        # 生成Mock测试配置
        test_code = self.generate_mock_test_config()
        with open(output_dir / "filter_test_config.py", "w", encoding="utf-8") as f:
            f.write(test_code)
        print("✅ 生成Mock测试配置")
        
        print("✅ 生成CSS样式文件")
        
        print(f"\n🎉 所有代码已生成到 {output_dir} 目录")
        print("\n📋 使用说明：")
        print("1. 复制 filter_html.html 中的内容到 templates/statistics.html")
        print("2. 复制 filter_js.js 中的内容到 static/js/statistics.js")
        print("3. 复制 filter_backend.py 中的内容到 app.py")
        print("4. 复制 filter_test_config.py 中的内容到测试配置文件")
        print("5. 复制 filter_styles.css 中的内容到 static/css/styles.css")
        
        # 显示支持的过滤器类型统计
        type_counts = {}
        for config in FILTER_CONFIGS:
            type_name = config.filter_type.value
            type_counts[type_name] = type_counts.get(type_name, 0) + 1
        
        print(f"\n📊 当前支持的过滤器类型:")
        for type_name, count in type_counts.items():
            print(f"   • {type_name}: {count} 个")

def main():
    """主函数"""
    generator = FilterCodeGenerator()
    generator.generate_all_code()

if __name__ == "__main__":
    main() 